﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using MiragePWF.Common.Commons;
using MiragePWF.UI.WinForm;
using Wolfut.MirageEE.Domain.CommonUtilities;
using Wolfut.MirageEE.UI.UICommonUtilities;

namespace Wolfut.MirageEE.UI.UIBaseComponents
{
    public partial class FormBase :  DevExpress.XtraEditors.XtraForm
    {
        public FormBase()
        {
            InitializeComponent();
        }
        private bool isDirty = false;

        private MirageEEFormUtility utility;

        /// <summary>
        /// application context
        /// </summary>
        [Browsable(false)]
        public virtual IApplicationContext ApplicationContext
        {
            get { return ApplicationContextFactory.GetApplicationContext(); }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!this.DesignMode)
            {
                this.Utility.AddControlToHashtable(this);
            }
        }


        /// <summary>
        /// This property is used to track the dirty state of the data on
        /// a form if change checking is enabled.
        /// </summary>
        [Browsable(false)]
        public virtual bool Dirty
        {
            get { return isDirty; }
            set { isDirty = value; }
        }

        /// <summary>
        /// Get a FormUitility instance to handle UI control.
        /// </summary>
        [Browsable(false)]
        protected FormUtility Utility
        {
            get
            {
                if (this.utility == null) this.utility = new MirageEEFormUtility();
                return this.utility;
            }
        }


        #region Set controls' state
        #region Set control visable
        /// <summary>
        /// Set visible property for control
        /// </summary>
        /// <param name="control">The parent control.</param>
        /// <param name="isVisible">The value of Visible property.</param>
        protected virtual void SetVisible(Control control, bool isVisible)
        {
            if (control is TabPage)
            {
                TabPage tabPage = (TabPage)control;
                TabControl tabControl = (TabControl)control.Parent;
                if (!isVisible)
                {
                    tabControl.TabPages.Remove(tabPage);
                }
            }
            else
            {
                PropertyInfo propertyInfo = control.GetType().GetProperty("Visible");
                if (propertyInfo != null)
                {
                    propertyInfo.SetValue(control, isVisible, null);
                }
            }
        }


        /// <summary>
        /// Set visible property for control
        /// </summary>
        /// <param name="control">The parent control.</param>
        protected virtual void SetPermanentInvisible(Control control)
        {
            if (control is TabPage)
            {
                TabPage tabPage = (TabPage)control;
                TabControl tabControl = (TabControl)control.Parent;
                if (tabControl.TabPages.IndexOf(tabPage) == 0)
                {
                    if (tabControl.TabPages.Count == 1)
                    {
                        tabControl.Visible = false;
                        return;
                    }
                    else
                    {
                        tabControl.TabPages[1].Select();
                    }
                }

                tabControl.TabPages.Remove(tabPage);
                if (tabControl.TabPages.Count >= 1)
                {
                    tabControl.SelectedTab = tabControl.TabPages[0];
                }

            }
            else
            {
                PropertyInfo propertyInfo = control.GetType().GetProperty("Visible");
                if (propertyInfo != null)
                {
                    propertyInfo.SetValue(control, false, null);
                    control.VisibleChanged += new EventHandler(Control_VisibleChanged);
                }
            }
        }

        /// <summary>
        /// The method provide to set the control visible property to false fixedly.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Control_VisibleChanged(object sender, EventArgs e)
        {
            ((Control)sender).VisibleChanged -= new EventHandler(Control_VisibleChanged);
            ((Control)sender).Visible = false;
            ((Control)sender).VisibleChanged += new EventHandler(Control_VisibleChanged);
        }
        #endregion

        #region Set control enabled
        /// <summary>
        /// Set control enabled property.
        /// </summary>
        /// <param name="control">A array of controls which need set enabled property.</param>
        /// <param name="isEnabled">enabled or disabled.</param>
        /// <param name="exclusiveControls">the controls would be exclusive.</param>
        protected virtual void SetEnabled(Control control, bool isEnabled, params Control[] exclusiveControls)
        {
            if (control.HasChildren)
            {
                foreach (Control childControl in control.Controls)
                {
                    this.SetEnabled(childControl, isEnabled, exclusiveControls);
                }
            }
            else if (!(control is Label) && !(control is Button))
            {

                if (exclusiveControls != null && exclusiveControls.Length > 0)
                {
                    foreach (Control compareControl in exclusiveControls)
                    {
                        if (compareControl.Name == control.Name)
                            return;
                    }
                }
                if (control is TextBoxBase)
                {
                    SetTextBoxEnabled(control, isEnabled);
                }
                else
                {
                    control.Enabled = isEnabled;
                    this.SetControlBackground(control);
                }
            }
        }

        /// <summary>
        /// Set control enabled property.
        /// </summary>
        /// <param name="controlArray">A array of controls which need set enabled property.</param>
        /// <param name="isEnabled">enabled or disabled.</param>
        protected void SetEnabled(Control[] controlArray, bool isEnabled)
        {
            foreach (Control control in controlArray)
            {
                if (control is TextBoxBase)
                {
                    SetTextBoxEnabled(control, isEnabled);
                }
                else
                {
                    control.Enabled = isEnabled;
                }
                this.SetControlBackground(control);
            }
        }

        /// <summary>
        /// Set control Disabled fixedly, the control wouldn't be set to enabled anymore.
        /// </summary>
        /// <param name="controlArray">A array of controls which need set enabled property.</param>		
        public void SetPermanentDisabled(Control[] controlArray)
        {
            foreach (Control control in controlArray)
            {
                if (control is TextBoxBase)
                {
                    SetTextBoxEnabled(control, false);
                    ((TextBoxBase)control).ReadOnlyChanged += new EventHandler(TextBoxBase_ReadOnlyChanged);
                }
                else
                {
                    control.Enabled = false;
                    control.EnabledChanged += new EventHandler(Control_EnabledChanged);
                }
                this.SetControlBackground(control);
            }
        }

        /// <summary>
        /// If set Textbox enabled to false, would cannot select the text, so set the readonly property instand of enabled property.
        /// </summary>
        /// <param name="control">A TextBox control which need set enabled property.</param>
        /// <param name="isEnabled">enabled or disabled.</param>
        public void SetTextBoxEnabled(Control control, bool isEnabled)
        {
            if (control is TextBoxBase)
            {
                TextBoxBase textBoxBase = (TextBoxBase)control;
                textBoxBase.ReadOnly = !isEnabled;
                textBoxBase.TabStop = isEnabled;
            }
        }

        /// <summary>
        /// Set the control's background manually if disable it, in order to let them 
        /// </summary>
        /// <param name="control"></param>
        protected virtual void SetControlBackground(Control control)
        {
            if (!(control is NumericUpDown || control is DateTimePicker)) return;

            if (control.Enabled)
            {
                control.BackColor = System.Drawing.SystemColors.Window;
                control.ForeColor = System.Drawing.SystemColors.WindowText;
            }
            else
            {
                control.BackColor = System.Drawing.SystemColors.Control;
                control.ForeColor = System.Drawing.SystemColors.GrayText;
            }
        }

        /// <summary>
        /// The method provide to set the control enabled property to false fixedly.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Control_EnabledChanged(object sender, EventArgs e)
        {
            ((Control)sender).EnabledChanged -= new EventHandler(Control_EnabledChanged);
            ((Control)sender).Enabled = false;
            ((Control)sender).EnabledChanged += new EventHandler(Control_EnabledChanged);
        }

        /// <summary>
        /// The method provide to set the TextBoxBase readonly property to true fixedly.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TextBoxBase_ReadOnlyChanged(object sender, EventArgs e)
        {
            ((TextBoxBase)sender).ReadOnlyChanged -= new EventHandler(TextBoxBase_ReadOnlyChanged);
            this.SetTextBoxEnabled((TextBoxBase)sender, false);
            ((TextBoxBase)sender).ReadOnlyChanged += new EventHandler(TextBoxBase_ReadOnlyChanged);
        }
        #endregion

        #region reset controls
        /// <summary>
        /// Set empty value for control and its child controls.
        /// </summary>
        /// <param name="control">the control need be clear.</param>
        public void ResetControl(Control control)
        {
            ResetControl(control, null);
        }

        /// <summary>
        /// Set empty value for control and its child controls.
        /// </summary>
        /// <param name="control">the control need be clear.</param>
        /// <param name="exclusiveControls">the controls are exclusived.</param>
        public virtual void ResetControl(Control control, params Control[] exclusiveControls)
        {
            if (exclusiveControls != null && exclusiveControls.Length > 0)
            {
                foreach (Control compareControl in exclusiveControls)
                {
                    if (compareControl.Name == control.Name)
                        return;
                }
            }

            if (control.HasChildren)
            {
                foreach (Control childControl in control.Controls)
                {
                    this.ResetControl(childControl, exclusiveControls);
                }
            }
            else
            {
                this.ResetSingleControl(control);
            }
        }


        /// <summary>
        /// Set empty value for control.
        /// </summary>
        /// <param name="control">The control to reset.</param>
        protected virtual void ResetSingleControl(Control control)
        {
            try
            {
                if (control is TextBoxBase)
                {
                    ((TextBoxBase)control).Clear();
                }
                else if (control is ListControl)
                {
                    ((ListControl)control).SelectedIndex = -1;
                    ((ListControl)control).SelectedIndex = -1;
                }
                else if (control is CheckBox || control is RadioButton)
                {
                    PropertyInfo propertyInfo = control.GetType().GetProperty("Checked");
                    propertyInfo.SetValue(control, false, null);
                }
                //TODO: handle NullableDateTimePicker
                //				else if (control is NullableDateTimePicker)
                //				{
                //					((NullableDateTimePicker)control).Value = ((NullableDateTimePicker)control).NullValue;
                //				}
            }
            catch (Exception ex)
            {
                throw new Exception("Control " + control.Name + " has error: " + ex.Message);
            }
        }
        #endregion
        #endregion
    } 
}
